package al.work.dataserialize.buildserial;

import sun.plugin.dom.exception.InvalidAccessException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author JiuZh
 */
public class build_serialize {

    public interface bs_crt_t<_DATA_T> {
        /**
         * 返回实际数据
         * @return
         */
        _DATA_T value();
        /**
         * 设置实际数据
         * @param _value
         */
        void value(_DATA_T _value);
        /**
         * 返回序列化需要的数据长度
         * @return
         */
        int length();
        /**
         * 序列化
         * @param _helper
         * @return
         */
        boolean serialize(i_stream_helper.i_out_stream _helper);
        /**
         * 构造
         * @param _helper
         * @return
         */
        boolean build(i_stream_helper.i_in_stream _helper);
    }

    public interface bs_crt_new_helper<_T extends bs_crt_t> {
        _T new_crt();
        int length();
    }

    public static class bs_crt_uint8 implements bs_crt_t<Short> {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_uint8> {
            public bs_crt_uint8 new_crt() {
                return new bs_crt_uint8();
            }
            public int length() {
                return bs_crt_uint8.type_length();
            }
        }
        private static bs_crt_new_helper s_new_helper_ = new bs_crt_new_helper();
        public static bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_uint8() { value_ = 0; }
        public bs_crt_uint8(short _value) { value_ = _value; }
        public bs_crt_uint8(Short _value) { value(_value); }

        public static int type_length() { return 1; }
        public int length() { return type_length(); }

        public Short value() { return value_; }
        public void value(Short _value) { value_ = (null == _value) ? 0 : _value.shortValue(); }
        public short base_value() { return value_; }
        public void base_value(short _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_uint_8(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Short value = _helper.read_uint_8();
            if (null == value) {
                return false;
            }
            value_ = value.shortValue();
            return true;
        }

        private short value_;
    }
    public static class bs_crt_uint16 implements bs_crt_t<Integer>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_uint16> {
            public bs_crt_uint16 new_crt() {
                return new bs_crt_uint16();
            }
            public int length() {
                return bs_crt_uint16.type_length();
            }
        }
        private static bs_crt_uint16.bs_crt_new_helper s_new_helper_ = new bs_crt_uint16.bs_crt_new_helper();
        public static bs_crt_uint16.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_uint16() { value_ = 0; }
        public bs_crt_uint16(int _value) { value_ = _value; }
        public bs_crt_uint16(Integer _value) { value(_value); }

        public static int type_length() { return 2; }
        public int length() { return type_length(); }

        public Integer value() { return value_; }
        public void value(Integer _value) { value_ = (null == _value) ? 0 : _value.intValue(); }
        public int base_value() { return value_; }
        public void base_value(int _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_uint_16(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Integer value = _helper.read_uint_16();
            if (null == value) {
                return false;
            }
            value_ = value.intValue();
            return true;
        }

        private int value_;
    }
    public static class bs_crt_uint32 implements bs_crt_t<Long>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_uint32> {
            public bs_crt_uint32 new_crt() {
                return new bs_crt_uint32();
            }
            public int length() {
                return bs_crt_uint32.type_length();
            }
        }
        private static bs_crt_uint32.bs_crt_new_helper s_new_helper_ = new bs_crt_uint32.bs_crt_new_helper();
        public static bs_crt_uint32.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_uint32() { value_ = 0; }
        public bs_crt_uint32(long _value) { value_ = _value; }
        public bs_crt_uint32(Long _value) { value(_value); }

        public static int type_length() { return 4; }
        public int length() { return type_length(); }

        public Long value() { return value_; }
        public void value(Long _value) { value_ = _value; }
        public long base_value() { return value_; }
        public void base_value(long _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_uint_32(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Long value = _helper.read_uint_32();
            if (null == value) {
                return false;
            }
            value_ = value.longValue();
            return true;
        }

        private long value_;
    }

    public static class bs_crt_int8 implements bs_crt_t<Byte>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_int8> {
            public bs_crt_int8 new_crt() {
                return new bs_crt_int8();
            }
            public int length() {
                return bs_crt_int8.type_length();
            }
        }
        private static bs_crt_int8.bs_crt_new_helper s_new_helper_ = new bs_crt_int8.bs_crt_new_helper();
        public static bs_crt_int8.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_int8() { value_ = 0; }
        public bs_crt_int8(byte _value) { value_ = _value; }
        public bs_crt_int8(Byte _value) { value(_value); }


        public static int type_length() { return 1; }
        public int length() { return type_length(); }

        public Byte value() { return value_; }
        public void value(Byte _value) { value_ = (null == _value) ? 0 : _value.byteValue(); }
        public byte base_value() { return value_; }
        public void base_value(byte _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_int_8(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Byte value = _helper.read_int_8();
            if (null == value) {
                return false;
            }
            value_ = value.byteValue();
            return true;
        }

        private byte value_;
    }
    public static class bs_crt_int16 implements bs_crt_t<Short>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_int16> {
            public bs_crt_int16 new_crt() {
                return new bs_crt_int16();
            }
            public int length() {
                return bs_crt_int16.type_length();
            }
        }
        private static bs_crt_int16.bs_crt_new_helper s_new_helper_ = new bs_crt_int16.bs_crt_new_helper();
        public static bs_crt_int16.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_int16() { value_ = 0; }
        public bs_crt_int16(short _value) { value_ = _value; }
        public bs_crt_int16(Short _value) { value(_value); }

        public static int type_length() { return 2; }
        public int length() { return type_length(); }

        public Short value() { return value_; }
        public void value(Short _value) { value_ = (null == _value) ? 0 : _value.shortValue(); }
        public short base_value() { return value_; }
        public void base_value(short _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_int_16(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Short value = _helper.read_int_16();
            if (null == value) {
                return false;
            }
            value_ = value.shortValue();
            return true;
        }

        private short value_;
    }
    public static class bs_crt_int32 implements bs_crt_t<Integer>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_int32> {
            public bs_crt_int32 new_crt() {
                return new bs_crt_int32();
            }
            public int length() {
                return bs_crt_int32.type_length();
            }
        }
        private static bs_crt_int32.bs_crt_new_helper s_new_helper_ = new bs_crt_int32.bs_crt_new_helper();
        public static bs_crt_int32.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_int32() { value_ = 0; }
        public bs_crt_int32(int _value) { value_ = _value; }
        public bs_crt_int32(Integer _value) { value(_value); }

        public static int type_length() { return 4; }
        public int length() { return type_length(); }

        public Integer value() { return value_; }
        public void value(Integer _value) { value_ = (null == _value) ? 0 : _value.intValue(); }
        public int base_value() { return value_; }
        public void base_value(int _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_int_32(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Integer value = _helper.read_int_32();
            if (null == value) {
                return false;
            }
            value_ = value.intValue();
            return true;
        }

        private int value_;
    }
    public static class bs_crt_int64 implements bs_crt_t<Long>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_int64> {
            public bs_crt_int64 new_crt() {
                return new bs_crt_int64();
            }
            public int length() {
                return bs_crt_int64.type_length();
            }
        }
        private static bs_crt_int64.bs_crt_new_helper s_new_helper_ = new bs_crt_int64.bs_crt_new_helper();
        public static bs_crt_int64.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_int64() { value_ = 0; }
        public bs_crt_int64(long _value) { value_ = _value; }
        public bs_crt_int64(Long _value) { value(_value); }

        public static int type_length() { return 8; }
        public int length() { return type_length(); }

        public Long value() { return value_; }
        public void value(Long _value) { value_ = (null == _value) ? 0 : _value.longValue(); }
        public long base_value() { return value_; }
        public void base_value(long _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_int_64(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Long value = _helper.read_int_64();
            if (null == value) {
                return false;
            }
            value_ = value.longValue();
            return true;
        }

        private long value_;
    }

    public static class bs_crt_float implements bs_crt_t<Float>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_float> {
            public bs_crt_float new_crt() {
                return new bs_crt_float();
            }
            public int length() {
                return bs_crt_float.type_length();
            }
        }
        private static bs_crt_float.bs_crt_new_helper s_new_helper_ = new bs_crt_float.bs_crt_new_helper();
        public static bs_crt_float.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_float() { value_ = 0; }
        public bs_crt_float(float _value) { value_ = _value; }
        public bs_crt_float(Float _value) { value(_value); }

        public static int type_length() { return 4; }
        public int length() { return type_length(); }

        public Float value() { return value_; }
        public void value(Float _value) { value_ = (null == _value) ? 0 : _value.floatValue(); }
        public float base_value() { return value_; }
        public void base_value(float _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_float(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Float value = _helper.read_float();
            if (null == value) {
                return false;
            }
            value_ = value.floatValue();
            return true;
        }

        private float value_;
    }
    public static class bs_crt_double implements bs_crt_t<Double>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_crt_double> {
            public bs_crt_double new_crt() {
                return new bs_crt_double();
            }
            public int length() {
                return bs_crt_double.type_length();
            }
        }
        private static bs_crt_double.bs_crt_new_helper s_new_helper_ = new bs_crt_double.bs_crt_new_helper();
        public static bs_crt_double.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_crt_double() { value_ = 0; }
        public bs_crt_double(double _value) { value_ = _value; }
        public bs_crt_double(Double _value) { value(_value); }

        public static int type_length() { return 8; }
        public int length() { return type_length(); }

        public Double value() { return value_; }
        public void value(Double _value) { value_ = (null == _value) ? 0 : _value.floatValue(); }
        public double base_value() { return value_; }
        public void base_value(double _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            return _helper.write_double(value_);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            Double value = _helper.read_double();
            if (null == value) {
                return false;
            }
            value_ = value.doubleValue();
            return true;
        }

        private double value_;
    }

    public static class bs_ustring_t implements bs_crt_t<String>  {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_ustring_t> {
            public bs_ustring_t new_crt() {
                return new bs_ustring_t();
            }
            public int length() {
                // error
                return -1;
            }
        }
        private static bs_ustring_t.bs_crt_new_helper s_new_helper_ = new bs_ustring_t.bs_crt_new_helper();
        public static bs_ustring_t.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_ustring_t() { value_ = null; }
        public bs_ustring_t(String _value) { value_ = _value; }

        public int length() {
            int length = bs_crt_uint32.type_length();
            if (null != value_) {
                try {
                    length += value_.getBytes("utf-8").length;
                } catch (Exception ex) {}
            }
            return length;
        }

        public String value() { return value_; }
        public void value(String _value) { value_ = _value; }
        public String base_value() { return value_; }
        public void base_value(String _value) { value_ = _value; }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            byte[] bytes = null;
            if (null != value_) {
                try {
                    bytes = value_.getBytes("utf-8");
                } catch (Exception ex) {}
            }

            bs_crt_uint32 count = new bs_crt_uint32((null == bytes) ? 0 : bytes.length);
            return count.serialize(_helper) && _helper.write_bytes(bytes);
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            bs_crt_uint32 count = new bs_crt_uint32();
            if (!count.build(_helper)) {
                return false;
            }
            byte[] bytes = new byte[count.value().intValue()];
            if(!_helper.read_bytes(bytes)) {
                return false;
            }

            try {
                value_ = new String(bytes, "utf-8");
            } catch (Exception ex) {
                value_ = "";
            }
            return true;
        }

        private String value_;
    }

    /**
     * 数组：保存基本数据类型,需要辅助解析器
     * @param <_DATA_T>
     * @param <_CRT_T>
     */
    public static class bs_list_st<_DATA_T, _CRT_T extends bs_crt_t> implements bs_crt_t<List<_DATA_T>> {

        public bs_list_st(bs_crt_new_helper<_CRT_T> _new_helper) {
            new_helper_ = _new_helper;
            value_ = new ArrayList<_DATA_T>(); }

        public int length() {
            int length = bs_crt_uint32.type_length();
            if (null != value_) {
                if (new_helper_.length() <= 0) {
                    _CRT_T crt_vl = new_helper_.new_crt();
                    for (_DATA_T single : value_) {
                        crt_vl.value(single);
                        length += crt_vl.length();
                    }
                } else {
                    length += new_helper_.length() * value_.size();
                }
            }
            return length;
        }

        public List<_DATA_T> value() { return value_; }
        public void value(List<_DATA_T> _value) { value_.clear(); value_.addAll(_value); }
        public List<_DATA_T> base_value() { return value_; }
        public void base_value(List<_DATA_T> _value) { value_.clear(); value_.addAll(_value); }

        public void clear() { value_.clear(); }
        public void add(_DATA_T _value) { value_.add(_value); }
        public void add(int _index, _DATA_T _value) { value_.add(_index, _value); }
        public void set(int _index, _DATA_T _value) { value_.set(_index, _value); }
        public void addAll(Collection<? extends _DATA_T> _collection) { value_.addAll(_collection); }
        public void addAll(int _index, Collection<? extends _DATA_T> _collection) { value_.addAll(_index, _collection); }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            bs_crt_uint32 count = new bs_crt_uint32(value_.size());
            if (!count.serialize(_helper)) {
                return false;
            }
            _CRT_T crt_vl = new_helper_.new_crt();
            for (_DATA_T single : value_) {
                crt_vl.value(single);
                if (!crt_vl.serialize(_helper)) {
                    return false;
                }
            }
            return true;
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            bs_crt_uint32 count = new bs_crt_uint32();
            if (!count.build(_helper)) {
                return false;
            }
            value_.clear();

            _CRT_T crt_vl = new_helper_.new_crt();
            for (long i = 0; i < count.base_value(); ++i) {
                if (!crt_vl.build(_helper)) {
                    return false;
                }
                value_.add((_DATA_T) crt_vl.value());
            }
            return true;
        }

        private bs_crt_new_helper<_CRT_T> new_helper_;
        private List<_DATA_T> value_;
    }

    /**
     * 数组：保存继承了bs_crt_t的类型，自带解析
     * @param <_CRT_T>
     */
    public static class bs_list_ot<_CRT_T extends bs_crt_t> implements bs_crt_t<List<_CRT_T>>  {

        public bs_list_ot(bs_crt_new_helper<_CRT_T> _new_helper) {
            new_helper_ = _new_helper;
            value_ = new ArrayList<_CRT_T>();
        }

        public int length() {
            int length = bs_crt_uint32.type_length();
            if (null != value_) {
                for (_CRT_T single : value_) {
                    length += single.length();
                }
            }
            return length;
        }

        public List<_CRT_T> value() { return value_; }
        public void value(List<_CRT_T> _value) { value_.clear(); value_.addAll(_value); }
        public List<_CRT_T> base_value() { return value_; }
        public void base_value(List<_CRT_T> _value) { value_.clear(); value_.addAll(_value); }

        public void clear() { value_.clear(); }
        public void add(_CRT_T _value) { value_.add(_value); }
        public void add(int _index, _CRT_T _value) { value_.add(_index, _value); }
        public void set(int _index, _CRT_T _value) { value_.set(_index, _value); }
        public void addAll(Collection<? extends _CRT_T> _collection) { value_.addAll(_collection); }
        public void addAll(int _index, Collection<? extends _CRT_T> _collection) { value_.addAll(_index, _collection); }

        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            bs_crt_uint32 count = new bs_crt_uint32(value_.size());
            if (!count.serialize(_helper)) {
                return false;
            }
            for (_CRT_T single : value_) {
                if (!single.serialize(_helper)) {
                    return false;
                }
            }
            return true;
        }
        public boolean build(i_stream_helper.i_in_stream _helper) {
            bs_crt_uint32 count = new bs_crt_uint32();
            if (!count.build(_helper)) {
                return false;
            }
            value_.clear();

            for (long i = 0; i < count.base_value(); ++i) {
                _CRT_T crt_vl = new_helper_.new_crt();
                if (!crt_vl.build(_helper)) {
                    return false;
                }
                value_.add(crt_vl);
            }
            return true;
        }

        private bs_crt_new_helper<_CRT_T> new_helper_;
        private List<_CRT_T> value_;
    }

    /**
     * 消息基类定义，所有自定义消息继承此结构，继承此类的结构字段最后可以不同步
     */
    public static abstract class bs_message_t implements bs_crt_t<bs_message_t> {

        /**
         * 返回实际数据
         * @return
         */
        public bs_message_t value() {
            return this;
        }
        /**
         * 设置实际数据
         * @param _value
         */
        public void value(bs_message_t _value) throws InvalidAccessException {
            throw new InvalidAccessException("can not set value with the function");
        }

        /**
         * 返回序列化需要的数据长度
         * @return
         */
        public int length() {
            return bs_crt_uint32.type_length() + child_length();
        }

        /**
         * 序列化
         * @param _helper
         * @return
         */
        public boolean serialize(i_stream_helper.i_out_stream _helper) {
            bs_crt_uint32 count = new bs_crt_uint32(child_length());
            if (!count.serialize(_helper)) {
                return false;
            }
            return child_serialize(_helper);
        }

        /**
         * 构造
         *
         * @param _helper
         * @return
         */
        public boolean build(i_stream_helper.i_in_stream _helper) {
            bs_crt_uint32 count = new bs_crt_uint32();
            if (!count.build(_helper)) {
                return false;
            }

            i_stream_helper.i_in_stream l_in_helper = _helper.child_stream((int)count.base_value());
            if (null == l_in_helper) {
                return false;
            }
            child_build(l_in_helper);
            // 此处失败只是一个子结构build失败，存在字段多了的情况，忽略
            return true;
        }

        /**
         * 子类的长度
         * @return
         */
        protected abstract int child_length();

        /**
         * 子类的序列化
         * @param _helper
         * @return
         */
        protected abstract boolean child_serialize(i_stream_helper.i_out_stream _helper);

        /**
         * 子类的结构化
         * @param _helper
         * @return
         */
        protected abstract boolean child_build(i_stream_helper.i_in_stream _helper);
    }

    /**
     * 空消息结构
     */
    public static class bs_null_t extends bs_message_t {

        public static class bs_crt_new_helper implements build_serialize.bs_crt_new_helper<bs_null_t> {
            public bs_null_t new_crt() {
                return new bs_null_t();
            }
            public int length() {
                // error
                return 0;
            }
        }
        private static bs_null_t.bs_crt_new_helper s_new_helper_ = new bs_null_t.bs_crt_new_helper();
        public static bs_null_t.bs_crt_new_helper new_helper() { return s_new_helper_; }

        public bs_null_t() {}

        public bs_null_t base_value() { return this; }

        /**
         * 子类的长度
         * @return
         */
        @Override
        protected int child_length() {
            return 0;
        }
        /**
         * 子类的序列化
         * @return
         */
        @Override
        protected boolean child_serialize(i_stream_helper.i_out_stream _helper) {
            return true;
        }
        /**
         * 子类的结构化
         * @param _helper
         * @return
         */
        @Override
        protected boolean child_build(i_stream_helper.i_in_stream _helper) {
            return true;
        }
    }
}
